#pragma once
#ifndef MODIFIES_H
#define MODIFIES_H
#include <vector>
#include <cassert>
#include <iosfwd>
#include <algorithm>
#include <iterator>
#include "Parent.h"
#include "ProcTable.h"
#include "spa_types.h"
#include <boost/dynamic_bitset.hpp>
#include <boost/unordered_map.hpp>
using namespace boost;

/*
typedef struct mod_entry {
		VARINDEX var_index;
	    dynamic_bitset<> mod_bitset;	
		PROCINDEX proc_index;
} MODENTRY;
*/

class Modifies
{

private:
	bool debug;
	friend class ModifiesTest;
	int num_of_statements;

	boost::unordered_map<VARINDEX, STMT_ARRAY> var_stmts;
	boost::unordered_map<VARINDEX, PROCINDEX_ARRAY> var_procs;
	boost::unordered_map<PROCINDEX, VARINDEX_ARRAY> proc_vars;
	boost::unordered_map<unsigned int, VARINDEX_ARRAY> stmt_vars;

	//STMT_ARRAY BitsetToStatementArray(boost::dynamic_bitset<> mod_bitset, NODETYPE node_type);
	STMT_ARRAY IdentifyParents(STMT_ARRAY children, NODETYPE node_type,  int r_n);
	void InitializeModifies(int num_of_statements); // only for maintainer's use
	Parent parent_test;
	ProcTable proc_test;
	//std::vector<MODENTRY> modifies_list;
public:
	
	Modifies(void);	
	~Modifies(void);	
	
	void InsertModifies(STMT statement, VARINDEX var_index, PROCINDEX proc_index);
	BOOLEAN GetAssignmentModifies(STMT statement, VARINDEX var_index);	
	VARINDEX GetVariableModifiedByAssignment(STMT statement);
	STMT_ARRAY GetAssignmentModifiesVariable(VARINDEX var_index);
	STMT_ARRAY GetContainerModifiesVariable(VARINDEX var_index, NODETYPE node_type);
	VARINDEX_ARRAY GetVariablesModifiedByContainer(STMT container);
	PROCINDEX_ARRAY GetProceduresModifiesVariable(VARINDEX var_index);
	VARINDEX_ARRAY GetVariablesModifiedByProcedure(PROCINDEX proc_index);

	// newly added
	BOOLEAN GetContainerModifies(STMT, VARINDEX, NODETYPE);
	BOOLEAN GetStatementModifies(STMT, VARINDEX);
	BOOLEAN GetProcedureModifies(PROCINDEX, VARINDEX);


	
};


#endif